package newclasses;

import java.util.Iterator;
import java.util.Random;
import java.util.Vector;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

import org.jfree.ui.RefineryUtilities;

import chart.XYAreaChartDemo2;

import src.RTPpacket;
import temp.TypeConverter;

public class Recovery {

	
	private static final int	EXTERNAL_BUFFER_SIZE = 100;
	
	private SoundRead soundReader;
	private Vector<RTPpacket> packets;
	private int milisecondsPerPacket;
	private RecoveryAlgorithm recoveryAlgorithm;
	private int windowLengthInPackets;
	private int templateLengthInBytes;

	
	
	public Recovery(int milisecondsPerPacket, int windowLengthInPackets,	int templateLengthInBytes) {
		super();
		this.soundReader = new SoundRead();
		this.packets = new Vector<RTPpacket>();
		this.milisecondsPerPacket = milisecondsPerPacket;
		this.windowLengthInPackets = windowLengthInPackets;
		this.templateLengthInBytes = templateLengthInBytes;
	}


	public void read(String sound){
		soundReader.readFileSound(sound);
		int bytesPerMiliseconds = soundReader.bytesPerMilisecondes();
		packets = soundReader.convertToPackets(milisecondsPerPacket * bytesPerMiliseconds);
		

		this.recoveryAlgorithm = new RecoveryAlgorithm(milisecondsPerPacket * soundReader.bytesPerMilisecondes(),windowLengthInPackets,templateLengthInBytes);
	}
	
	public int getLengthPacket() {
		
		int bytesPerMiliseconds = soundReader.bytesPerMilisecondes();
		return (milisecondsPerPacket * bytesPerMiliseconds);
	}
	
	
	public void simulateLoss(int nLosses){
				
		Random random = new Random();	
		for (int i = 0; i < nLosses; i++){
			packets.setElementAt(null,random.nextInt(packets.size() - 1) + 1);
		}	
	
	}
	
	public Vector<Byte> simulateLoss1(int nLosses){
		
		Random random = new Random();	
		for (int i = 0; i < nLosses; i++){
			System.out.println(packets.size());
			packets.remove(random.nextInt(packets.size() - 1) + 1);
		}	
	
				
		Iterator<RTPpacket> i = packets.iterator();
		int bytesPerMiliseconds = soundReader.bytesPerMilisecondes();
		byte data[] = new byte[milisecondsPerPacket * bytesPerMiliseconds];
		Vector<Byte> samples = new Vector<Byte>();
		RTPpacket p;
		int length = 0;
		
		while(i.hasNext())
		{
			p = i.next();
			p.getpayload(data);
			length = p.getpayload_length();

			for (int j = 0; j < length ;  j++) {
				samples.add(data[j]);
			}
		}
				
		return samples;		
		
	}
	
	public Vector<Byte> recovery(){
		Iterator<RTPpacket> iterator = packets.iterator();
		Vector<Byte> temp; 
		Vector<Byte> recovered = new Vector<Byte>(packets.size());
		
		while(iterator.hasNext()){
			
			temp = recoveryAlgorithm.add(iterator.next());
			recovered.addAll(temp);
		}
		
		return recovered;
	}
	
	
	public Vector<Byte> getOriginalFile() {
		
		Iterator<RTPpacket> i = packets.iterator();
		byte data[] = new byte[getLengthPacket()];
		Vector<Byte> samples = new Vector<Byte>();
		RTPpacket p;
		int length = 0;
		
		while(i.hasNext())
		{
			p = i.next();
			p.getpayload(data);
			length = p.getpayload_length();

			for (int j = 0; j < length ;  j++) {
				samples.add(data[j]);
			}
		}
				
		return samples;		
		
	}
	
	
	
	
	public void play(Vector<Byte> sound){
		SourceDataLine	line = null;
		DataLine.Info	info = new DataLine.Info(SourceDataLine.class,
												 soundReader.getAudioFormat());
		try
		{
			line = (SourceDataLine) AudioSystem.getLine(info);
			line.open(soundReader.getAudioFormat());
		}
		catch (LineUnavailableException e)
		{
			e.printStackTrace();
			System.exit(1);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.exit(1);
		}

	
		line.start();
		
		Iterator<Byte> i = sound.iterator();
		byte[]	abData = new byte[EXTERNAL_BUFFER_SIZE];
		int count = 0;
		
		while(i.hasNext())
		{
			abData[count++] = i.next();
			
			if(count == abData.length)
			{
				 line.write(abData, 0, count);
				count = 0;
			}	
		}
		
		line.write(abData, 0, count);
		
		
		line.drain();
		line.close();
	}
	
	
	
	public static void main(String[] args) {
		
		Recovery r = new Recovery(100,20,20);
		
		r.read("wave1.wav");
		
		
		Vector<Byte> soundOriginal = r.getOriginalFile();
		
		
		r.simulateLoss(10);
		
		Vector<Byte> sound = r.recovery();
	    
		
	    
		r.play(sound);
		
		Vector<Short> soundInShort = new Vector<Short>();
		
		Iterator<Byte> iterator = sound.iterator();
		
		while(iterator.hasNext()){
			soundInShort.add(TypeConverter.byteSignedToUnsegned(iterator.next()));
		}
		
		Vector<Short> soundOriginalInShort = new Vector<Short>();
		Iterator<Byte> iteratorOr = soundOriginal.iterator();
		
		while(iteratorOr.hasNext()){
			soundOriginalInShort.add(TypeConverter.byteSignedToUnsegned(iteratorOr.next()));
		}
		
			XYAreaChartDemo2 demo = new XYAreaChartDemo2("teste", soundInShort,soundOriginalInShort,"1","2");
			demo.pack();
			RefineryUtilities.centerFrameOnScreen(demo);
			demo.setVisible(true);	    	



		
	}
	
	
	
}
